home *** CD-ROM | disk | FTP | other *** search
/ Programming Sound Cards / Programming Sound Cards.iso / sound_31 / musgus.asm < prev    next >
Assembly Source File  |  1995-01-01  |  69KB  |  2,435 lines

  1. segment         GUSSound
  2. assume          cs:GUSSound,ds:GUSSound
  3.  
  4. StartSoundSeg   = $
  5.  
  6. proc            MUS
  7.                 push    ax bx cx dx bp ds es
  8.                 push    ax
  9.                 mov     ax,cs
  10.                 mov     ds,ax
  11.                 mov     es,ax
  12.                 pop     ax
  13.                 cld
  14.                 cmp     bx,0fh
  15.                 ja      @@HigherThanWeCount
  16.                 cmp     bx,0
  17.                 jz      @@DoIt
  18.                 cmp     [cs:MUSOK],1
  19.                 jnz     @@HigherThanWeCount
  20. @@DoIt:         shl     bx,1
  21.                 call    [Word bx+JumpTable]
  22. @@HigherThanWeCount:
  23.                 pop     es ds bp dx cx bx ax
  24.                 retf
  25. endp            MUS
  26.  
  27.                 db      13,10,'Gravis UltraSound MOD Routines v2.1',0
  28.                 db      13,10,'By Joshua C. Jensen',0
  29. JumpTable       dw      offset MUS_Init                 ; Function 00
  30.                 dw      offset MUS_Close                ; Function 01
  31.                 dw      offset MUS_SetVars              ; Function 02
  32.                 dw      offset MUS_Nothing              ; Function 03
  33.                 dw      offset MUS_PlayMusic            ; Function 04
  34.                 dw      offset MUS_StopMusic            ; Function 05
  35.         dw    offset MUS_Nothing        ; Function 06
  36.                 dw      offset MUS_SpeakerOn            ; Function 07
  37.                 dw      offset MUS_SpeakerOff           ; Function 08
  38.                 dw      offset MUS_ReturnInfo           ; Function 09
  39.                 dw      offset MUS_SetInfo              ; Function 0A
  40.                 dw      offset MUS_RetVoice             ; Function 0B
  41.                 dw      offset MUS_RetMusicStatus       ; Function 0C
  42.                 dw      offset MUS_DumpSampleDRAM       ; Function 0D
  43.  
  44. ;include     "ptable.inc"
  45.  
  46. MUSOK           db      0
  47. PS16Header:
  48. Sig        db    'PS16■'
  49. SongName    db    75 dup (0)
  50. SongLen     db    0
  51. numpatterns    db    0
  52. commentofs    dd    0
  53. Sequences    db    128 dup (0)
  54. Samples     db    31*size PS16Sample dup (0)
  55. PS16Size    =    $-PS16Header
  56.  
  57. PatternLoc      dw      64 dup (0)
  58. InsLoc          dd      32 dup (0)
  59. NumPatterns     dw      0
  60. Mus             SMus    <>
  61. NumLines    db    0
  62. MusBuf        dw    0
  63. ChannelMap    db    32 dup (0)
  64. ChannelPriority db    32 dup (0)
  65.  
  66. include         "vect.rt"
  67.  
  68. ;▓────────────────────────────────────────────────────────────────────────────▓
  69. ; MUS_Nothing - Dead...
  70. ;▓────────────────────────────────────────────────────────────────────────────▓
  71. proc            MUS_Nothing near
  72.                 ret
  73. endp            MUS_Nothing
  74.  
  75. ;▓────────────────────────────────────────────────────────────────────────────▓
  76. ; MUS_Init - Initialize the music routines.
  77. ;   AX - GF1 IRQ     (0 for detect)
  78. ;   CX - MIDI IRQ
  79. ;   DX - Base port   (0 for detect)
  80. ;   SI - DMA IN
  81. ;   DI - DMA OUT
  82. ;   Carry set - No Gravis Ultrasound
  83. ; Returns:
  84. ;   SI - IRQ
  85. ;   DI - Port
  86. ;▓────────────────────────────────────────────────────────────────────────────▓
  87. proc            MUS_Init near
  88.                 call    u_DetectGUS
  89.                 jnb     @@FoundGUS
  90.                 xor     si,si
  91.                 xor     di,di
  92.                 ret
  93. @@FoundGUS:     mov     bx,[cs:GUSIRQ]
  94.                 mov     si,cs
  95.                 mov     di,offset GUSInt
  96.                 call    SetVect
  97.                 mov     [Word cs:IntStore],di
  98.                 mov     [Word cs:IntStore+2],si
  99.                 call    u_Reset
  100.                 call    MUS_SetMaxVolume
  101.         mov    [Word cs:Mus+(offset (SMus).HeaderLoc)],offset PS16Header
  102.                 mov     [Word cs:Mus+(offset (SMus).HeaderLoc)+2],cs
  103. ;         mov     [Word cs:Mus+(offset (SMus).AnalyzerLoc)],offset AnalyzerHeights
  104. ;         mov     [Word cs:Mus+(offset (SMus).AnalyzerLoc)+2],cs
  105.                 mov     [Word cs:Mus+(offset (SMus).PatternLoc)],offset PatternLoc
  106.                 mov     [Word cs:Mus+(offset (SMus).PatternLoc)+2],cs
  107.                 mov     [Word cs:Mus+(offset (SMus).InsLoc)],offset InsLoc
  108.                 mov     [Word cs:Mus+(offset (SMus).InsLoc)+2],cs
  109.                 mov     [Word cs:Mus+(offset (SMus).ChannelLoc)],offset Channel1
  110.                 mov     [Word cs:Mus+(offset (SMus).ChannelLoc)+2],cs
  111.                 mov     [Word cs:Mus+(offset (SMus).mt_PeriodTable)],offset mt_PeriodTable
  112.                 mov     [Word cs:Mus+(offset (SMus).mt_PeriodTable)+2],cs
  113.                 mov     [Byte cs:MUSOK],1
  114.                 mov     si,[cs:GUSIRQ]
  115.                 mov     di,[cs:u_Base]
  116.                 clc
  117.                 ret
  118. endp            MUS_Init
  119.  
  120.  
  121. ;▓────────────────────────────────────────────────────────────────────────────▓
  122. ; MUS_Close - Kill all allocated segs, etc.
  123. ;▓────────────────────────────────────────────────────────────────────────────▓
  124. proc            MUS_Close near
  125.                 call    MUS_StopMusic
  126.                 call    u_Reset
  127.                 mov     bx,[cs:GUSIRQ]
  128.                 mov     di,[Word cs:IntStore]
  129.                 mov     si,[Word cs:IntStore+2]
  130.                 call    RestoreVect
  131.                 mov     [Byte cs:MUSOK],0
  132.                 ret
  133. endp            MUS_Close
  134.  
  135.  
  136. ;▓────────────────────────────────────────────────────────────────────────────▓
  137. ; MUS_SetVars - Sets various parameters for the card.
  138. ;   AX - Sampling Rate (on SB, ignored here...)
  139. ;   CL - Max Volume Setting
  140. ;   CH - IRQ = 0 if default
  141. ;   DX - GUS address
  142. ;▓────────────────────────────────────────────────────────────────────────────▓
  143. proc            MUS_SetVars near
  144.                 mov     [cs:MaxVolume],cl
  145.                 or      ch,ch
  146.                 jz      @@NoIRQChange
  147.                 mov     [Byte cs:GUSIRQ],ch
  148. @@NoIRQChange:  or      dx,dx
  149.                 jz      @@NoAddrChange
  150.                 mov     [cs:u_Base],dx
  151.                 add     dx,102h
  152.                 mov     [cs:u_Voice],dx
  153.                 inc     dx
  154.                 mov     [cs:u_Command],dx
  155.                 inc     dx
  156.                 mov     [cs:u_DataLo],dx
  157.                 inc     dx
  158.                 mov     [cs:u_DataHi],dx
  159.                 mov     dx,[cs:u_Base]
  160.                 add     dx,6
  161.                 mov     [cs:u_Status],dx
  162.                 add     dx,2
  163.                 mov     [cs:u_TimerControl],dx
  164.                 inc     dx
  165.                 mov     [cs:u_TimerData],dx
  166. @@NoAddrChange: ret
  167. endp            MUS_SetVars
  168.  
  169.  
  170. ;▓────────────────────────────────────────────────────────────────────────────▓
  171. ; MUS_PlayMusic - Make proper calls and interrupt sets for module playing.
  172. ; In: cx:si - PM Structure
  173. ;▓────────────────────────────────────────────────────────────────────────────▓
  174.  
  175. proc            MUS_PlayMusic near
  176.                 push    ds
  177.                 mov     ds,cx
  178.         mov    ax,[si+(offset (PM).MusBuf)+2]
  179.         mov    [cs:MusBuf],ax
  180.         mov    ax,[si+PM.mt_speed]
  181.                 cmp     ax,-1
  182.                 jz      @@SkipSpeed
  183.                 mov     [Word cs:mt_speed],ax
  184. @@SkipSpeed:    mov     ax,[si+PM.mt_counter]
  185.                 cmp     ax,-1
  186.                 jz      @@SkipCounter
  187.                 mov     [Word cs:mt_counter],ax
  188. @@SkipCounter:  mov     ax,[si+PM.mt_SongPos]
  189.                 mov     [word cs:mt_SongPos],ax
  190.                 mov     ax,[si+PM.mt_PatternPos]
  191.                 mov     [Word cs:mt_PatternPos],ax
  192.                 mov     ax,cs
  193.                 mov     es,ax
  194.         mov    di,offset PS16Header
  195.                 push    ds si
  196.                 lds     si,[si+PM.Header]
  197.         mov    cx,PS16Size
  198.                 rep     movsb
  199.                 pop     si ds
  200.                 mov     di,offset PatternLoc
  201.                 push    ds si
  202.                 lds     si,[si+PM.PatternLoc]
  203.                 mov     cx,64*2
  204.                 rep     movsb
  205.                 pop     si ds
  206.                 mov     di,offset InsLoc
  207.                 push    ds si
  208.                 lds     si,[si+PM.InsLoc]
  209.                 mov     cx,32*4
  210.                 rep     movsb
  211.                 pop     si ds
  212.                 mov     [Byte cs:MStatus],0
  213.         call    MUS_SetVoice
  214.         call    u_Reset
  215.                 mov     bx,6
  216.                 call    u_TurnOnUserInt
  217.                 pop     ds
  218.                 ret
  219. endp            MUS_PlayMusic
  220.  
  221.  
  222. ;▓────────────────────────────────────────────────────────────────────────────▓
  223. ; MUS_StopMusic - Shuts down the interrupts for generating music.
  224. ;▓────────────────────────────────────────────────────────────────────────────▓
  225.  
  226. proc            MUS_StopMusic near
  227.                 mov     [Byte cs:MStatus],1
  228.                 call    u_TurnOffUserInt
  229.                 call    u_Reset
  230.                 ret
  231. endp            MUS_StopMusic
  232.  
  233.  
  234. ;▓────────────────────────────────────────────────────────────────────────────▓
  235. ; MUS_SpeakerOn - Turns output speaker on.
  236. ;▓────────────────────────────────────────────────────────────────────────────▓
  237. proc            MUS_SpeakerOn near
  238.                 mov     dx,[cs:u_Base]
  239.                 mov     al,00000000b
  240.                 out     dx,al
  241.                 ret
  242. endp            MUS_SpeakerOn
  243.  
  244.  
  245. ;▓────────────────────────────────────────────────────────────────────────────▓
  246. ; MUS_SpeakerOff - Turns output speaker off.
  247. ;▓────────────────────────────────────────────────────────────────────────────▓
  248. proc            MUS_SpeakerOff near
  249.                 mov     dx,[cs:u_Base]
  250.                 mov     al,00000010b
  251.                 out     dx,al
  252.                 ret
  253. endp            MUS_SpeakerOff
  254.  
  255. ;▓────────────────────────────────────────────────────────────────────────────▓
  256. ; MUS_ReturnInfo - Returns the SMUS structure location in SI:DI.
  257. ; In:
  258. ;   CX - 1 = Copy info to SI:DI.
  259. ;        0 = Just return pointer.
  260. ;▓────────────────────────────────────────────────────────────────────────────▓
  261. proc            MUS_ReturnInfo near
  262.                 mov     ax,[cs:NumPatterns]
  263.                 mov     [cs:offset Mus+(offset (SMus).NumPatterns)],ax
  264.                 mov     al,[cs:mt_speed]
  265.                 mov     [cs:offset Mus+(offset (SMus).mt_speed)],al
  266.                 mov     al,[cs:mt_counter]
  267.                 mov     [cs:offset Mus+(offset (SMus).mt_counter)],al
  268.                 mov     ax,[cs:mt_PatternPos]
  269.                 mov     [cs:offset Mus+(offset (SMus).mt_PatternPos)],ax
  270.                 mov     al,[cs:mt_SongPos]
  271.                 mov     [cs:offset Mus+(offset (SMus).mt_SongPos)],al
  272.                 mov     al,[cs:PlayStatus]
  273.                 mov     [cs:offset Mus+(offset (SMus).PlayStatus)],al
  274.                 mov     ax,[cs:EditSeg]
  275.                 mov     [cs:offset Mus+(offset (SMus).EditSeg)],ax
  276.                 mov     ax,[cs:EditPat]
  277.                 mov     [cs:offset Mus+(offset (SMus).EditPat)],ax
  278.                 mov     ax,[cs:EditOfs]
  279.                 mov     [cs:offset Mus+(offset (SMus).EditOfs)],ax
  280.                 mov     al,[cs:MaxVolume]
  281.                 mov     [cs:offset Mus+(offset (SMus).MaxVolume)],al
  282.         mov    al,[cs:SongLen]
  283.                 mov     [cs:offset Mus+(offset (SMus).songlen)],al
  284.                 or      cx,cx
  285.                 jnz     @@CopyIt
  286.                 mov     si,cs
  287.                 mov     di,offset Mus
  288.                 ret
  289. @@CopyIt:       push    ds es
  290.                 mov     es,si
  291.                 mov     ax,cs
  292.                 mov     ds,ax
  293.                 mov     si,offset Mus
  294.                 mov     cx,size Mus
  295.                 rep     movsb
  296.                 pop     es ds
  297.                 ret
  298. endp            MUS_ReturnInfo
  299.  
  300. ;▓────────────────────────────────────────────────────────────────────────────▓
  301. ; MUS_SetInfo - Sets the SMUS structure location to whatever is in SI:DI.
  302. ; In:
  303. ;   CX - 1 = Set Max Volume
  304. ;        2 = Set Pattern Info
  305. ;▓────────────────────────────────────────────────────────────────────────────▓
  306. proc            MUS_SetInfo near
  307.                 push    cx ds es
  308.                 mov     ds,si
  309.                 mov     si,di
  310.                 mov     ax,cs
  311.                 mov     es,ax
  312.                 mov     di,offset Mus
  313.                 mov     cx,size Mus
  314.                 rep     movsb
  315.                 pop     es ds
  316.                 pop     cx
  317.                 cli
  318.                 mov     ax,[cs:offset Mus+(offset (SMus).NumPatterns)]
  319.                 mov     [cs:NumPatterns],ax
  320.                 test    cx,2
  321.                 jz      @@SkipSetPat
  322.                 mov     al,[cs:offset Mus+(offset (SMus).mt_speed)]
  323.                 mov     [cs:mt_speed],al
  324.                 mov     al,[cs:offset Mus+(offset (SMus).mt_counter)]
  325.                 mov     [cs:mt_counter],al
  326.                 mov     ax,[cs:offset Mus+(offset (SMus).mt_PatternPos)]
  327.                 mov     [cs:mt_PatternPos],ax
  328.                 mov     [cs:EditOfs],ax
  329.                 mov     al,[cs:offset Mus+(offset (SMus).mt_SongPos)]
  330.                 mov     [cs:mt_SongPos],al
  331.                 mov     [Byte PTr cs:EditPat],al
  332.                 mov     al,[cs:offset Mus+(offset (SMus).PlayStatus)]
  333.                 mov     [cs:PlayStatus],al
  334. @@SkipSetPat:   mov     al,[cs:offset Mus+(offset (SMus).MaxVolume)]
  335.                 mov     [cs:MaxVolume],al
  336.                 mov     al,[cs:offset Mus+(offset (SMus).songlen)]
  337.         mov    [cs:SongLen],al
  338.                 test    cx,1
  339.                 jz      @@Leave
  340.                 call    MUS_SetMaxVolume
  341. @@Leave:        sti
  342.                 ret
  343. endp            MUS_SetInfo
  344.  
  345. ;▓────────────────────────────────────────────────────────────────────────────▓
  346. ; MUS_RetVoice
  347. ;   In: AX - Voice
  348. ;       ES:DX - Buffer from DRAM
  349. ;       CX - Length
  350. ;▓────────────────────────────────────────────────────────────────────────────▓
  351. ; Dump sample to DRAM
  352. ;   ES:BX - Max 64k sample to dump to RAM.
  353. ;   SI:DI - DRAM location to dump to.
  354. ;   CX    - Max bytes to dump.
  355. ;   AH    - Xor value.
  356. proc            MUS_RetVoice near
  357.                 call    u_ReadPos
  358.                 call    u_Peek
  359.                 mov     si,ax
  360.                 ret
  361. endp            MUS_RetVoice
  362.  
  363.  
  364. ;▓────────────────────────────────────────────────────────────────────────────▓
  365. ; MUS_RetMusicStatus
  366. ;  Out: SI - 1  Music Stopped
  367. ;       DI - 1  Scope Triggered
  368. ;▓────────────────────────────────────────────────────────────────────────────▓
  369. proc            MUS_RetMusicStatus near
  370.                 mov     al,[cs:MStatus]
  371.                 xor     ah,ah
  372.                 mov     si,ax
  373.                 mov     al,[cs:Trigger]
  374.                 xor     ah,ah
  375.                 mov     di,ax
  376.                 mov     [Byte cs:Trigger],0
  377.                 ret
  378. endp            MUS_RetMusicStatus
  379.  
  380.  
  381. ;▓────────────────────────────────────────────────────────────────────────────▓
  382. ; MUS_DumpSampleDRAM
  383. ; CX - Sample Size
  384. ; SI:DI - Place in DRAM
  385. ; AX - Handle
  386. ;▓────────────────────────────────────────────────────────────────────────────▓
  387. proc            MUS_DumpSampleDRAM near
  388.                 mov     bx,ax
  389.                 call    LoadDumpSample
  390.                 ret
  391. endp            MUS_DumpSampleDRAM
  392.  
  393. ; CX - Sample Size
  394. ; SI:DI - Place in DRAM
  395. ; BX - Handle
  396. ; DX - Sample Seg to read
  397. LDSeg           dw      0
  398. proc            LoadDumpSample near
  399.                 push    cx bx
  400.         mov    [cs:LDSeg],dx
  401.                 pop     bx
  402.                 push    ds
  403.                 mov     ah,3Fh
  404.                 mov     dx,0
  405.                 mov     ds,[cs:LDSeg]
  406.                 int     21h
  407.                 pop     ds
  408.  
  409.                 pop     cx
  410.                 mov     es,[cs:LDSeg]
  411.                 mov     bx,0
  412.                 mov     ah,0
  413.                 call    u_DumpSampleToDRAM
  414.                 ret
  415. endp            LoadDumpSample
  416.  
  417. ;▓────────────────────────────────────────────────────────────────────────────▓
  418. ; MUS_SetMaxVolume - Set the Master volumes for the channels to the max value.
  419. ;▓────────────────────────────────────────────────────────────────────────────▓
  420. proc            MUS_SetMaxVolume near
  421.                 mov     al,[Byte cs:MaxVolume]
  422.                 mov     [cs:offset Channel1+(offset (MS).MasterVolume)],al
  423.                 mov     [cs:offset Channel2+(offset (MS).MasterVolume)],al
  424.                 mov     [cs:offset Channel3+(offset (MS).MasterVolume)],al
  425.                 mov     [cs:offset Channel4+(offset (MS).MasterVolume)],al
  426.                 ret
  427. endp            MUS_SetMaxVolume
  428.  
  429. ;▓────────────────────────────────────────────────────────────────────────────▓
  430. ; MUS_SetVoice -
  431. ;▓────────────────────────────────────────────────────────────────────────────▓
  432. proc        MUS_SetVoice near
  433.         mov    cx,16
  434.         mov    bx,offset Channel1
  435. @@Looper:    mov    ax,0
  436.         mov    [Word cs:bx+MS.start],ax
  437.         mov    ax,0f000h
  438.         mov    [Word cs:bx+(offset (MS).start)+2],ax
  439.         add    bx,size MS
  440.         loop    @@Looper
  441.         ret
  442. endp        MUS_SetVoice
  443.  
  444. ; GUS card routines.
  445.  
  446. MaxVoices    = 31
  447.  
  448. IntStore        dd      0
  449.  
  450. MIDIIRQ         dw      0
  451. GUSIRQ          dw      0
  452. DMAIn           dw      0
  453. DMAOut          dw      0
  454. u_Base          dw      0
  455.  
  456. proc    UDelay
  457.         push    dx ax
  458.         mov     dx,300h
  459.         in      al,dx
  460.         in      al,dx
  461.         in      al,dx
  462.         in      al,dx
  463.         in      al,dx
  464.         in      al,dx
  465.         in      al,dx
  466.         pop     ax dx
  467.         ret
  468. endp    UDelay
  469.  
  470. ; BX:CX Set to whatever.
  471. proc    u_Peek
  472.         pushf
  473.         cli
  474.         push    dx
  475.         mov     dx,[cs:u_Command]
  476.         mov     al,43h
  477.         out     dx,al
  478.         inc     dx                      ; 104h
  479.         mov     ax,cx
  480.         out     dx,ax
  481.         dec     dx                      ; 103h
  482.         mov     al,44h
  483.         out     dx,al
  484.         add     dx,2
  485.         mov     al,bl
  486.         out     dx,al
  487.         add     dx,2
  488.         in      al,dx
  489.         pop     dx
  490.         popf
  491.         ret
  492. endp    u_Peek
  493.  
  494. ; BX:CX Set to whatever.
  495. ; AX Value to poke
  496. proc    u_Poke
  497.         pushf
  498.         cli
  499.         push    dx ax
  500.         mov     dx,[cs:u_Command]
  501.         mov     al,43h
  502.         out     dx,al
  503.         inc     dx
  504.         mov     ax,cx
  505.         out     dx,ax
  506.         dec     dx
  507.         mov     al,44h
  508.         out     dx,al
  509.         add     dx,2
  510.         mov     al,bl
  511.         out     dx,al
  512.         add     dx,2
  513.         pop     ax
  514.         out     dx,al
  515.         in      al,dx
  516.         pop     dx
  517.         popf
  518.         ret
  519. endp    u_Poke
  520.  
  521.  
  522. ; DX - u_Base.
  523. proc    u_Probe
  524.         pushf
  525.         cli
  526.         mov     dx,[cs:u_Command]
  527.         mov     al,4Ch
  528.         out     dx,al
  529.         add     dx,2                    ; 105h
  530.         mov     al,0
  531.         out     dx,al
  532.         call    UDelay
  533.         call    UDelay
  534.         sub     dx,2                    ; 103h
  535.         mov     al,4Ch
  536.         out     dx,al
  537.         add     dx,2                    ; 105h
  538.         mov     al,1
  539.         out     dx,al
  540.         call    UDelay
  541.         call    UDelay
  542.         mov     ax,0AAh
  543.         mov     bx,0
  544.         mov     cx,0
  545.         call    u_Poke
  546.         mov     ax,055h
  547.         mov     bx,1
  548.         call    u_Poke
  549.         mov     bx,0
  550.         call    u_Peek
  551.         push    ax
  552.         mov     ax,0
  553.         call    u_Poke
  554.         sub     dx,2                    ; 103h
  555.         mov     al,4Ch
  556.         out     dx,al
  557.         add     dx,2                    ; 105h
  558.         mov     al,0
  559.         out     dx,al
  560.         pop     ax
  561.         popf
  562.         cmp     al,0AAh
  563.         jnz     @@Nope
  564.         clc
  565.         ret
  566. @@Nope: stc
  567.         ret
  568. endp    u_Probe
  569.  
  570. GUSChangeIRQ    db      0,0,1,3,0,2,0,4,0,0,0,5,6,0,0,7
  571. GUSChangeDMA    db      1,0,2,0,3,4,5
  572.                        ;1       5
  573. proc    u_SetInterface
  574.         cmp     [Word cs:GUSIRQ],0
  575.         jz      @@Exit
  576.         cli
  577.         mov     bx,[cs:MIDIIRQ]
  578.         mov     cl,[cs:bx+GUSChangeIRQ]
  579.         shl     cl,3
  580.         mov     bx,[cs:GUSIRQ]
  581.         or      cl,[cs:bx+GUSChangeIRQ]
  582.         cmp     bx,[cs:MIDIIRQ]
  583.         jnz     @@JustStore
  584.         or      cl,40h
  585. @@JustStore:
  586.         push    cx
  587.         mov     bx,[cs:DMAOut]
  588.         dec     bx
  589.         mov     cl,[cs:bx+GUSChangeDMA]
  590.         mov     dx,cx
  591.         shl     dl,3
  592.         mov     bx,[cs:DMAIn]
  593.         dec     bx
  594.         mov     cl,[cs:bx+GUSChangeDMA]
  595.         inc     bx
  596.         cmp     bx,[cs:DMAOut]
  597.         jnz     @@Fix
  598.         or      cl,40h
  599.         jmp     @@JustStore2
  600. @@Fix:  or      cl,dl
  601. @@JustStore2:
  602.         mov     bl,cl
  603.         pop     cx
  604.         mov     dx,[cs:u_Base]
  605.         mov     al,8
  606.         out     dx,al
  607.         add     dx,0Bh
  608.         mov     al,bl
  609.         or      al,80h
  610.         out     dx,al
  611.         mov     dx,[cs:u_Base]
  612.         mov     al,48h
  613.         out     dx,al
  614.         add     dx,0Bh
  615.         mov     al,cl
  616.         out     dx,al
  617.         mov     dx,[cs:u_Base]
  618.         mov     al,8
  619.         out     dx,al
  620.         add     dx,0Bh
  621.         mov     al,bl
  622.         out     dx,al
  623.         mov     dx,[cs:u_Base]
  624.         mov     al,48h
  625.         out     dx,al
  626.         add     dx,0Bh
  627.         mov     al,cl
  628.         out     dx,al
  629.         mov     dx,[cs:u_Base]
  630.         add     dx,102h
  631.         mov     al,0
  632.         out     dx,al
  633.         mov     dx,[cs:u_Base]
  634.         mov     al,9
  635.         out     dx,al
  636.         mov     dx,[cs:u_Base]
  637.         add     dx,102h
  638.         mov     al,0
  639.         out     dx,al
  640.         sti
  641. @@Exit: ret
  642. endp    u_SetInterface
  643.  
  644. proc    u_Reset
  645.         call    u_SetInterface
  646.         cli
  647.         mov     bx,[cs:u_Command]
  648.         mov     cx,[cs:u_DataHi]
  649.         mov     dx,bx
  650.         mov     al,4Ch
  651.         out     dx,al
  652.         mov     dx,cx
  653.         mov     al,0
  654.         out     dx,al
  655.         call    UDelay
  656.         call    UDelay
  657.         mov     dx,bx
  658.         mov     al,4Ch
  659.         out     dx,al
  660.         mov     dx,cx
  661.         mov     al,1
  662.         out     dx,al
  663.         call    UDelay
  664.         call    UDelay
  665.  
  666.         mov     dx,[cs:u_Voice]
  667.         add     dx,100h
  668.         mov     al,3
  669.         out     dx,al
  670.         call    UDelay
  671.         mov     dx,[cs:u_Voice]
  672.         add     dx,100h
  673.         mov     al,0
  674.         out     dx,al
  675.  
  676.  
  677.         mov     dx,bx
  678.         mov     al,41h
  679.         out     dx,al
  680.         mov     dx,cx
  681.         mov     al,0
  682.         out     dx,al
  683.         mov     dx,bx
  684.         mov     al,45h
  685.         out     dx,al
  686.         mov     dx,cx
  687.         mov     al,0
  688.         out     dx,al
  689.         mov     dx,bx
  690.         mov     al,49h
  691.         out     dx,al
  692.         mov     dx,cx
  693.         mov     al,0
  694.         out     dx,al
  695.  
  696.         mov     dx,bx
  697.         mov     al,0Eh
  698.         out     dx,al
  699.         add     dx,2
  700.         mov     al,MaxVoices
  701.         or      al,0C0h
  702.         out     dx,al
  703.  
  704.         mov     dx,[cs:u_Status]
  705.         in      al,dx
  706.         mov     dx,bx
  707.         mov     al,41h
  708.         out     dx,al
  709.         mov     dx,cx
  710.         in      al,dx
  711.         mov     dx,bx
  712.         mov     al,49h
  713.         out     dx,al
  714.         mov     dx,cx
  715.         in      al,dx
  716.         mov     dx,bx
  717.         mov     al,8Fh
  718.         out     dx,al
  719.         mov     dx,cx
  720.         in      al,dx
  721.  
  722.         push    bx cx
  723.         mov     cx,0
  724. @@VoiceClearLoop:
  725.         mov     dx,[cs:u_Voice]
  726.         mov     al,cl
  727.         out     dx,al
  728.         inc     dx
  729.         mov     al,9
  730.         out     dx,al
  731.         inc     dl
  732.         mov     ax,0
  733.         out     dx,ax
  734.         dec     dl
  735.         mov     al,0
  736.         out     dx,al
  737.         add     dx,2
  738.         mov     al,3                    ; Turn voice off
  739.         out     dx,al
  740.         sub     dx,2
  741.         mov     al,0Dh
  742.         out     dx,al
  743.         add     dx,2
  744.         mov     al,3
  745.         out     dx,al
  746.         sub     dx,2
  747.         inc     cx
  748.         cmp     cx,32
  749.         jnz     @@VoiceClearLoop
  750.         pop     cx bx
  751.  
  752.         mov     dx,bx
  753.         mov     al,41h
  754.         out     dx,al
  755.         mov     dx,cx
  756.         in      al,dx
  757.         mov     dx,bx
  758.         mov     al,49h
  759.         out     dx,al
  760.         mov     dx,cx
  761.         in      al,dx
  762.         mov     dx,bx
  763.         mov     al,8Fh
  764.         out     dx,al
  765.         mov     dx,cx
  766.         in      al,dx
  767.  
  768.         mov     dx,bx
  769.         mov     al,4Ch
  770.         out     dx,al
  771.         mov     dx,cx
  772.         mov     al,7
  773.         out     dx,al
  774.         sti
  775.         ret
  776. endp    u_Reset
  777.  
  778. ; CX:AX  - Number
  779. proc    RShift
  780.         mov     bx,cx
  781.         shr     ax,7
  782.         shr     cx,7
  783.         shl     bx,9
  784.         or      ax,bx
  785.         ret
  786. endp    RShift
  787.  
  788. ; AX - Voice
  789. ; Returns:  DX:AX - Position
  790. proc    u_ReadPos
  791.         pushf
  792.         cli
  793.         mov     dx,[cs:u_Voice]
  794.         out     dx,al
  795.         inc     dx              ; 103h
  796.         mov     al,8ah
  797.         out     dx,al
  798.         inc     dx              ; 104h
  799.         in      ax,dx           ; TEMP0
  800.         mov     cx,ax
  801.         dec     dx              ; 103h
  802.         mov     al,8bh
  803.         out     dx,al
  804.         inc     dx              ; 104h
  805.         in      ax,dx           ; TEMP1
  806.         xor     dx,dx
  807.         mov     bx,cx
  808.         shl     cx,7
  809.         shl     dx,7
  810.         shr     bx,9
  811.         or      dx,bx
  812.         shr     ax,9
  813.         and     ax,7Fh
  814.         or      cx,ax
  815.         mov     ax,cx
  816.         popf
  817.         ret
  818. endp    u_ReadPos
  819.  
  820. ; Dump sample to DRAM
  821. ;   ES:BX - Max 64k sample to dump to RAM.
  822. ;   SI:DI - DRAM location to dump to.
  823. ;   CX    - Max bytes to dump.
  824. ;   AH    - Xor value.
  825. proc    u_DumpSampleToDRAM
  826.         cli
  827.         push    cx
  828.         mov     dx,[cs:u_Command]
  829.         mov     al,44h          ; Dump upper byte, only do it on carry from now
  830.         out     dx,al           ; on.
  831.         add     dx,2
  832.         push    ax
  833.         mov     ax,si
  834.         out     dx,al
  835.         pop     ax
  836.         sub     dx,2
  837. @@MainLoop:
  838.         mov     al,43h
  839.         out     dx,al
  840.         inc     dx
  841.         push    ax
  842.         mov     ax,di
  843.         out     dx,ax
  844.         pop     ax
  845.         dec     dx
  846. @@DumpByte:
  847.         add     dx,4
  848.         mov     al,[es:bx]
  849.         xor     al,ah
  850.         inc     bx
  851.         out     dx,al
  852.         sub     dx,4
  853.         add     di,1
  854.         jnc     @@DoLoop
  855.         inc     si
  856.         mov     al,44h
  857.         out     dx,al
  858.         add     dx,2
  859.         push    ax
  860.         mov     ax,si
  861.         out     dx,al
  862.         pop     ax
  863.         sub     dx,2
  864. @@DoLoop:
  865.         loop    @@MainLoop
  866.         pop     cx
  867.         sti
  868.         ret
  869. endp    u_DumpSampleToDRAM
  870.  
  871. u_Voice         dw      0
  872. u_Command       dw      0
  873. u_DataLo        dw      0
  874. u_DataHi        dw      0
  875. u_Status        dw      0
  876. u_TimerControl  dw      0
  877. u_TimerData     dw      0
  878. u_adlibcontrol  db      0
  879. u_timermask     db      0
  880. u_IRQs          db      2,3,5,7,11,12,15
  881. u_IntStore      dd      0,0,0,0,0,0,0
  882.  
  883. proc    u_SetPorts
  884.         mov     dx,[cs:u_Base]
  885.         add     dx,102h
  886.         mov     [cs:u_Voice],dx
  887.         inc     dx
  888.         mov     [cs:u_Command],dx
  889.         inc     dx
  890.         mov     [cs:u_DataLo],dx
  891.         inc     dx
  892.         mov     [cs:u_DataHi],dx
  893.         mov     dx,[cs:u_Base]
  894.         add     dx,6
  895.         mov     [cs:u_Status],dx
  896.         add     dx,2
  897.         mov     [cs:u_TimerControl],dx
  898.         inc     dx
  899.         mov     [cs:u_TimerData],dx
  900.         ret
  901. endp    u_SetPorts
  902.  
  903. ; In:
  904. ;   DX - Base   (0 for detect)
  905. ;   CX - MIDI IRQ
  906. ;   AX - IRQ    (0 for detect)
  907. ; Carry set - No GUS
  908. ; No carry  - GUS at u_Base
  909. proc    u_DetectGUS
  910.         mov     [cs:GUSIRQ],ax
  911.         mov     [cs:MIDIIRQ],cx
  912.         mov     [cs:DMAIn],si
  913.         mov     [cs:DMAOut],di
  914.         mov     [cs:u_Base],dx
  915.         call    u_SetPorts
  916.         clc
  917.         ret
  918. endp    u_DetectGUS
  919.  
  920. ; bx - Speed (0-255)  (* 80 microseconds)
  921. proc            u_TurnOnUserInt
  922.                 cli
  923.                 or      [Byte cs:u_adlibcontrol],4
  924.                 or      [Byte cs:u_timermask],1
  925.                 mov     dx,[cs:u_Command]
  926.                 mov     al,46h
  927.                 out     dx,al
  928.                 add     dx,2
  929.                 mov     al,bl
  930.                 out     dx,al
  931.                 sub     dx,2
  932.                 mov     al,45h
  933.                 out     dx,al
  934.                 add     dx,2
  935.                 mov     al,[cs:u_adlibcontrol]
  936.                 out     dx,al
  937.                 mov     dx,[cs:u_TimerControl]
  938.                 mov     al,4
  939.                 out     dx,al
  940.                 inc     dx
  941.                 mov     al,[cs:u_timermask]
  942.                 out     dx,al
  943.                 sti
  944.                 ret
  945. endp            u_TurnOnUserInt
  946.  
  947. proc            u_TurnOffUserInt
  948.                 cli
  949.                 and     [Byte cs:u_adlibcontrol],0FBh
  950.                 and     [Byte cs:u_timermask],0FEh
  951.                 mov     dx,[cs:u_Command]
  952.                 mov     al,45h
  953.                 out     dx,al
  954.                 add     dx,2
  955.                 mov     al,[cs:u_adlibcontrol]
  956.                 out     dx,al
  957.                 call    u_Reset
  958.                 sti
  959.                 ret
  960. endp            u_TurnOffUserInt
  961.  
  962. irqstatus       db      0
  963.  
  964. proc            GUSInt
  965.                 pusha
  966.                 push    ds es
  967.         mov    dx,[cs:u_Status]
  968.                 in      al,dx
  969.                 mov     [cs:irqstatus],al
  970. @@TopOfInt:     test    [Byte cs:irqstatus],4
  971.                 jz      @@CheckNext
  972.                 mov     dx,[cs:u_Command]
  973.                 mov     al,45h
  974.                 out     dx,al
  975.                 and     [Byte cs:u_adlibcontrol],0FBh
  976.                 add     dx,2
  977.                 mov     al,[cs:u_adlibcontrol]
  978.                 out     dx,al
  979.                 or      [Byte cs:u_adlibcontrol],4
  980.                 mov     al,[cs:u_adlibcontrol]
  981.                 out     dx,al
  982.         call    sd_UpdateChannels
  983.                 cmp     [Byte cs:MStatus],1
  984.                 jnz     @@CheckNext
  985.                 call    u_TurnOffUserInt
  986.                 call    u_Reset
  987. @@CheckNext:    mov     dx,[cs:u_Command]
  988.                 mov     al,8Fh
  989.                 out     dx,al
  990.                 add     dx,2
  991.                 in      al,dx
  992. @@Finish:
  993.                 mov     al,20h
  994.                 out     0A0h,al
  995.                 mov     al,20h
  996.                 out     20h,al
  997.                 sti
  998.  
  999.                 pop     es ds
  1000.                 popa
  1001.                 iret
  1002. endp            GUSInt
  1003.  
  1004.  
  1005. proc        FindOpenChannel
  1006.         mov    bx,0
  1007. @@Looper:    cmp    [cs:bx+ChannelMap],0
  1008.         jz    @@Open
  1009.         inc    bx
  1010.         cmp    bx,32
  1011.         jnz    @@Looper
  1012.  
  1013.         ; If we made it this far, check the priorities to turn one off.
  1014.         mov    dx,0
  1015.         mov    cx,0FFh     ; Max Priority
  1016.         mov    bx,0
  1017. @@PLooper:    cmp    [cs:bx+ChannelPriority],cl
  1018.         jl    @@Change
  1019.         jmp    @@IncIt
  1020. @@Change:    mov    cl,[cs:bx+ChannelPriority]
  1021.         mov    dx,bx
  1022. @@IncIt:        inc     bx
  1023.         cmp    bx,32
  1024.         jnz    @@PLooper
  1025.         mov    bx,ax
  1026.  
  1027.  
  1028. @@Open:     mov    ax,bx
  1029.         ret
  1030. endp            FindOpenChannel
  1031.  
  1032. ;┌──────────────────────────────────────────────────────────────────────────┐
  1033. ;│││──────────────────────── Protracker Stuff ────────────────────────────│││
  1034. ;└──────────────────────────────────────────────────────────────────────────┘
  1035. ;┌─┐ Protracker specific
  1036. ;└─┘ variables.
  1037. mt_speed                db      6
  1038. mt_counter              db      0
  1039. mt_PatternPos           dw      0
  1040. mt_SongPos              db      0
  1041. mt_PattDelayTime2       db      0
  1042. mt_PattDelayTime        db      0
  1043. mt_PBreakFlag           db      0
  1044. mt_PBreakPos            db      0
  1045. mt_PosJumpFlag          db      0
  1046. mt_LowMask              db      0FFh
  1047. Trigger                 db      0
  1048.  
  1049. mt_VibratoTable:        db        0, 24, 49, 74, 97,120,141,161
  1050.                         db      180,197,212,224,235,244,250,253
  1051.                         db      255,253,250,244,235,224,212,197
  1052.                         db      180,161,141,120, 97, 74, 49, 24
  1053.  
  1054. Channel1  MS <0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 0,0,0>
  1055. Channel2  MS <0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 1,0,0>
  1056. Channel3  MS <0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 2,0,0>
  1057. Channel4  MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 3,0,0>
  1058. Channel5  MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 4,0,0>
  1059. Channel6  MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 5,0,0>
  1060. Channel7  MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 6,0,0>
  1061. Channel8  MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 7,0,0>
  1062. Channel9  MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 , 8,0,0>
  1063. Channel10 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11, 9,0,0>
  1064. Channel11 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,10,0,0>
  1065. Channel12 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 ,11,0,0>
  1066. Channel13 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 ,12,0,0>
  1067. Channel14 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,13,0,0>
  1068. Channel15 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,14,0,0>
  1069. Channel16 MS <0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 ,15,0,0>
  1070.  
  1071.  
  1072. PlayStatus      db      1
  1073. MStatus         db      0
  1074. EditPat         dw      0
  1075. EditSeg         dw      0
  1076. EditOfs         dw      0
  1077. ChangeIns       db      0
  1078. MaxVolume    db    200
  1079. EfxFlag         db      0
  1080.  
  1081. mt_VolTable    dw    00E00h,0B000h,0B800h,0BC00h,0BE00h,0C000h,0C400h,0C800h,0CC00h
  1082.         dw    0D000h,0D200h,0D400h,0D600h,0D800h,0DA00h,0DC00h,0DE00h
  1083.         dw    0E000h,0E100h,0E200h,0E300h,0E400h,0E500h,0E600h,0E700h
  1084.         dw    0E800h,0E900h,0EA00h,0EB00h,0EC00h,0ED00h,0EE00h,0EF00h
  1085.         dw    0F080h,0F100h,0F180h,0F200h,0F280h,0F300h,0F380h,0F400h
  1086.         dw    0F480h,0F500h,0F580h,0F600h,0F680h,0F700h,0F780h,0F800h
  1087.         dw    0F880h,0F900h,0F980h,0FA00h,0FA80h,0FB00h,0FB80h,0FC00h
  1088.                 dw      0FC80h,0FD00h,0FD80h,0FE00h,0FE80h,0FF00h,0FF80h,0FFF0h
  1089.  
  1090. include "period.asm"
  1091.  
  1092. macro   SetVoice
  1093.         mov     [Byte cs:Voice],cl
  1094.         mov     dx,[cs:u_Voice]
  1095.         mov     al,[cs:si+MS.sc_Voice]
  1096.         out     dx,al
  1097. endm    SetVoice
  1098.  
  1099. Voice   db      0
  1100.  
  1101. macro   PlayVol
  1102.         local   Done
  1103.         mov     dx,[cs:u_Command]
  1104.         mov     al,89h
  1105.         out     dx,al
  1106.         inc     dl
  1107.         in      ax,dx
  1108.         cmp     ax,[cs:si+MS.sc_Vol]
  1109.         jz      Done
  1110.         mov     ax,[cs:si+MS.sc_Vol]
  1111.         call    slideramp
  1112. Done:
  1113. endm    PlayVol
  1114.  
  1115. macro   PlayNote
  1116.         local   Done
  1117.         mov     dx,[cs:u_Command]
  1118.         mov     al,81h
  1119.         out     dx,al
  1120.         inc     dl
  1121.         in      ax,dx
  1122.         cmp     ax,[cs:si+MS.sc_Note]
  1123.         jz      Done
  1124.         dec     dl
  1125.         mov     al,1
  1126.         out     dx,al
  1127.         inc     dl
  1128.         mov     ax,[cs:si+MS.sc_Note]
  1129.         out     dx,ax
  1130. Done:
  1131. endm    PlayNote
  1132.  
  1133. proc        DecompressPattern near
  1134.         push    di
  1135.         mov    ax,es
  1136.         mov    ds,ax
  1137.         mov    ax,[cs:MusBuf]
  1138.         mov    es,ax
  1139.         mov    di,0
  1140.         mov    cx,3072/2
  1141.         mov    ax,0
  1142.         rep    stosw
  1143.         mov    si,0
  1144.         mov    di,0
  1145.                 mov     al,[si+2]
  1146.         mov    [cs:NumLines],al
  1147.         add    si,3
  1148.         mov    cx,0
  1149. @@ChannelLoop:    push    cx
  1150.         mov    di,cx
  1151.         shl    cx,1
  1152.         add    di,cx            ; * 3
  1153. @@LineLoop:    xor    ah,ah
  1154.         lodsb
  1155.         cmp    al,-1
  1156.         jz    @@NextChannel
  1157.         push    di
  1158.         mov    bx,ax
  1159.         shl    ax,5            ; * 32
  1160.         shl    bx,4            ; * 16
  1161.         add    di,ax
  1162.         add    di,bx
  1163.         movsb
  1164.         movsw
  1165.         pop    di
  1166.         jmp    @@LineLoop
  1167. @@NextChannel:    pop    cx
  1168.         inc    cx
  1169.         cmp    cx,16
  1170.         jnz    @@ChannelLoop
  1171.         pop    di
  1172.         ret
  1173. endp            DecompressPattern
  1174.  
  1175. ;╒═══════════════════════════════════════════════════════════════════════════╕
  1176. ;│ NAME       : sd_UpdateChannels                                            │
  1177. ;│              *** Original code: Amiga Protracker by Lars Hamre.           │
  1178. ;│              *** Converted by Joshua C. Jensen.                           │
  1179. ;╘═══════════════════════════════════════════════════════════════════════════╛
  1180. proc    DecProc near
  1181.         cmp     [cs:si+MS.DecVolume],0
  1182.         ja      @@AllRight
  1183.         mov     [Byte cs:si+MS.DecVolume],1
  1184. @@AllRight:
  1185.         dec     [Byte cs:si+MS.DecVolume]
  1186.         ret
  1187. endp    DecProc
  1188.  
  1189. proc    sd_UpdateChannels near
  1190.         mov     ax,cs
  1191.         mov     ds,ax
  1192.         mov     es,ax
  1193.  
  1194. mt_ContinueUpdate:
  1195.         inc     [Byte cs:mt_counter]
  1196.         mov     al,[cs:mt_counter]
  1197.         cmp     al,[cs:mt_speed]
  1198.         jb      mt_NoNewNote
  1199.         mov     [Byte cs:mt_counter],0
  1200.         cmp     [Byte cs:mt_PattDelayTime2],0
  1201.         jz      mt_GetNewNote
  1202.         call    mt_NoNewAllChannels
  1203.         jmp     mt_dskip
  1204.  
  1205. mt_NoNewNote:
  1206.         call    mt_NoNewAllChannels
  1207.         jmp     mt_NoNewPosYet
  1208.  
  1209. mt_NoNewAllChannels:
  1210.     mov    cx,16
  1211.         mov     si,offset Channel1
  1212. mt_NoNewLoop:
  1213.         push    cx si
  1214.         call    DecProc
  1215.         SetVoice
  1216.     call    mt_CheckEfx
  1217.         PlayNote
  1218.         PlayVol
  1219.         pop     si
  1220.         add     si,size MS
  1221.         pop     cx
  1222.         loop    mt_NoNewLoop
  1223.     ret
  1224.  
  1225. mt_GetNewNote:
  1226.         xor     ax,ax
  1227.         mov     al,[cs:mt_SongPos]
  1228.         mov     di,ax
  1229.         mov     [Word cs:EditPat],ax
  1230.     mov    al,[cs:di+Sequences]
  1231.         shl     al,1
  1232.         mov     di,offset PatternLoc
  1233.         add     di,ax
  1234.         mov     es,[cs:di]
  1235.         mov     di,[cs:mt_PatternPos]
  1236.     call    DecompressPattern
  1237.     mov    [Word cs:EditSeg],es
  1238.         mov     [Word cs:EditOfs],di
  1239.  
  1240.     mov    cx,16
  1241.         mov     si,offset Channel1
  1242. mt_GetNewLoop:
  1243.         push    cx si
  1244.         call    DecProc
  1245.         SetVoice
  1246.         call    mt_PlayVoice
  1247.         PlayNote
  1248.         PlayVol
  1249.         pop     si
  1250.         add     si,size MS
  1251.         pop     cx
  1252.         loop    mt_GetNewLoop
  1253.         jmp     mt_dskip
  1254.  
  1255. mt_PlayVoice:
  1256.         mov     [Byte cs:EfxFlag],0
  1257.         mov     [Byte cs:ChangeIns],0
  1258.     cmp    [Byte cs:si],0
  1259.         jnz     mt_plvskip
  1260.     cmp    [Word cs:si+1],0
  1261.         jnz     mt_plvskip
  1262.         call    mt_PerNop
  1263. mt_plvskip:
  1264.     mov    al,[es:di]
  1265.     mov    [cs:si+MS.note],al
  1266.     mov    ax,[es:di+1]
  1267.         mov     [Word cs:si+MS.cmd],ax
  1268.     add    di,3
  1269.  
  1270.         mov     al,[cs:si+MS.cmd]
  1271.         and     al,0F0h
  1272.         shr     al,4
  1273.         mov     ah,[Byte cs:si+MS.note]
  1274.     and    ah,11000000b
  1275.     shr    ah,2
  1276.         or      al,ah                   ; Is there an ins?
  1277.         jz      mt_SetRegisters
  1278.         mov     [Byte cs:ChangeIns],1
  1279.         mov     [cs:si+MS.sc_Mode],0
  1280.         dec     al
  1281.         mov     bl,al
  1282.         mov     [cs:si+MS.SampleNum],al
  1283.     mov    bh,size PS16Sample
  1284.     mul    bh
  1285.     mov    dx,ax
  1286.  
  1287.         xor     bh,bh
  1288.         shl     bx,2
  1289.         add     bx,offset InsLoc
  1290.         mov     ax,[cs:bx]
  1291.         mov     [Word cs:si+MS.start],ax
  1292.         mov     ax,[cs:bx+2]
  1293.         mov     [Word cs:si+(offset (MS).start)+2],ax
  1294.     mov    bx,dx
  1295.     add    bx,offset Samples
  1296.     mov    cx,[cs:bx+PS16Sample.length]
  1297.         mov     [Word cs:si+MS.length],cx
  1298.         mov     [Word cs:si+(offset (MS).length)+2],0
  1299.     mov    ax,[Word cs:bx+PS16Sample.volume]
  1300.         mov     [Word cs:si+MS.finetune],ax
  1301.         mov     al,ah
  1302.         call    volequ
  1303.  
  1304.     mov    cx,[cs:bx+PS16Sample.replen]; Get the Repeat length.
  1305.         cmp     cx,2
  1306.         jbe     mt_NoLoop
  1307.         or      [Byte cs:si+MS.sc_Mode],00001000b
  1308.     mov    cx,[cs:bx+PS16Sample.repeat]
  1309.         or      cx,cx
  1310.         je      mt_LoopNoFix
  1311.     dec    cx
  1312. mt_LoopNoFix:
  1313.         mov     ax,[Word cs:si+MS.start]
  1314.         mov     dx,[Word cs:si+(offset (MS).start)+2]
  1315.         add     ax,cx
  1316.         adc     dx,0
  1317.         mov     [Word cs:si+MS.loopstart],ax
  1318.         mov     [Word cs:si+(offset (MS).loopstart)+2],dx
  1319.         mov     [Word cs:si+MS.wavestart],ax
  1320.         mov     [Word cs:si+(offset (MS).wavestart)+2],dx
  1321.     mov    cx,[Word cs:bx+PS16Sample.replen]
  1322. ;     dec     cx
  1323.     add    ax,cx
  1324.         adc     dx,0
  1325.         mov     [Word cs:si+MS.replen],ax
  1326.         mov     [Word cs:si+(offset (MS).replen)+2],dx
  1327.         jmp     mt_SetRegisters
  1328. mt_NoLoop:
  1329.         mov     ax,[Word cs:si+MS.start]
  1330.         mov     dx,[Word cs:si+(offset (MS).start)+2]
  1331.         mov     [Word cs:si+MS.loopstart],ax
  1332.         mov     [Word cs:si+(offset (MS).loopstart)+2],dx
  1333.         mov     [Word cs:si+MS.wavestart],ax
  1334.         mov     [Word cs:si+(offset (MS).wavestart)+2],dx
  1335.     mov    cx,[Word cs:bx+PS16Sample.length]
  1336.         dec     cx
  1337.         add     ax,cx
  1338.         adc     dx,0
  1339.         mov     [Word cs:si+MS.replen],ax
  1340.         mov     [Word cs:si+(offset (MS).replen)+2],dx
  1341. mt_SetRegisters:
  1342.     mov    al,[cs:si+MS.note]
  1343.     and    al,00111111b
  1344.         jnz     mt_ThereIsANote
  1345.         jmp     mt_CheckMoreEfx
  1346. mt_ThereIsANote:
  1347.         mov     ax,[Word cs:si+MS.cmd]
  1348.         xchg    ah,al
  1349.         and     ax,0FF0h
  1350.         cmp     ax,0E50h
  1351.         jz      mt_DoSetFineTune
  1352.         cmp     ah,3                    ; Is it a tone portamento?
  1353.         jz      mt_ChkTonePorta
  1354.         cmp     ah,5                    ; Is it a tone and volume slide?
  1355.         jz      mt_ChkTonePorta
  1356.         cmp     ah,9                    ; Is it a sample offset command?
  1357.         jnz     mt_SetPeriod
  1358.         call    mt_CheckMoreEfx
  1359.         jmp     mt_SetPeriod
  1360.  
  1361. mt_DoSetFineTune:
  1362.         call    mt_SetFineTune
  1363.         jmp     mt_SetPeriod
  1364.  
  1365. mt_ChkTonePorta:
  1366.         call    mt_SetTonePorta
  1367.         jmp     mt_CheckMoreEfx
  1368.  
  1369. mt_SetPeriod:
  1370.         mov     [Byte cs:ChangeIns],1
  1371.     mov    bl,[cs:si+MS.note]
  1372.     and    bx,00111111b
  1373.     dec    bx
  1374.     shl    bx,1
  1375.     mov    al,[cs:si+MS.finetune]
  1376.     mov    cl,61*2
  1377.         mul     cl
  1378.         add     bx,ax
  1379.     mov    ax,[Word cs:bx+mt_PeriodTable]
  1380.         mov     [cs:si+MS.period],ax
  1381.  
  1382.         mov     ax,[Word cs:si+MS.cmd]
  1383.         xchg    ah,al
  1384.         and     ax,0FF0h
  1385.         cmp     ax,0ED0h
  1386.         jnz     mt_NotANoteCut
  1387.         jmp     mt_CheckMoreEfx
  1388. mt_NotANoteCut:
  1389.         mov     al,[cs:si+MS.wavecontrol]  ; Get the wavecontrol.
  1390.         and     al,00000100b            ; Amiga: BTST #2,wavecontrol.
  1391.         jz      mt_vibnoc               ; If it is zero, then skip.
  1392.         mov     [Byte cs:si+MS.vibratopos],0
  1393. mt_vibnoc:
  1394.         mov     al,[cs:si+MS.wavecontrol]  ; Get it again.
  1395.         and     al,01000000b            ; Amiga: BTST #6,wavecontrol
  1396.         jz      mt_trenoc               ; If it is zero, then skip.
  1397.         mov     [Byte cs:si+MS.tremolopos],0 ; Zero the Tremolo offset.
  1398. mt_trenoc:
  1399.         cmp     [Byte cs:ChangeIns],1
  1400.         jnz     mt_SetGeneral
  1401. mt_DoIns:
  1402.         ; high byte of sample start == F000H, turn off the voice
  1403.         cmp     [Word cs:si+(offset (MS).start)+2],0f000h
  1404.         jz      @@NoVoice
  1405.         push    dx ax
  1406.         mov     al,0
  1407.         call    doramp
  1408.         mov     dx,[cs:u_Command]
  1409.         mov     al,0
  1410.         out     dx,al
  1411.         mov     al,3
  1412.         add     dl,2
  1413.         out     dx,al
  1414.     xor    [cs:si+MS.sc_Voice],16
  1415.         mov     dx,[cs:u_Voice]
  1416.         mov     al,[cs:si+MS.sc_Voice]
  1417.         out     dx,al
  1418.         pop     ax dx
  1419.  
  1420.         ; Send sample begin
  1421. @@DoBegin:
  1422.         mov     dx,[cs:u_Command]
  1423.         mov     al,0ah
  1424.         out     dx,al
  1425.         inc     dx              ; 104h
  1426.         mov     ax,[Word cs:si+MS.start]
  1427.         mov     cx,[Word cs:si+(offset (MS).start)+2]
  1428.         call    RShift
  1429.         out     dx,ax
  1430.         dec     dx              ; 103h
  1431.         mov     al,0bh
  1432.         out     dx,al
  1433.         inc     dx              ; 104h
  1434.         mov     ax,[Word cs:si+MS.start]
  1435.         shl     ax,9
  1436.         out     dx,ax
  1437.  
  1438.         mov     dx,[cs:u_Command]
  1439.         mov     al,2
  1440.         out     dx,al
  1441.         inc     dx              ; 104h
  1442.         mov     ax,[Word cs:si+MS.loopstart]
  1443.         mov     cx,[Word cs:si+(offset (MS).loopstart)+2]
  1444.         call    RShift
  1445.         out     dx,ax
  1446.         dec     dx              ; 103h
  1447.         mov     al,3
  1448.         out     dx,al
  1449.         inc     dx              ; 104h
  1450.         mov     ax,[Word cs:si+MS.loopstart]
  1451.         shl     ax,9
  1452.         out     dx,ax
  1453.  
  1454.         mov     dx,[cs:u_Command]
  1455.         mov     al,4
  1456.         out     dx,al
  1457.         inc     dx              ; 104h
  1458.         mov     ax,[Word cs:si+MS.replen]
  1459.         mov     cx,[Word cs:si+(offset (MS).replen)+2]
  1460.         call    RShift
  1461.         out     dx,ax
  1462.         dec     dx              ; 103h
  1463.         mov     al,5
  1464.         out     dx,al
  1465.         inc     dx              ; 104h
  1466.         mov     ax,[Word cs:si+MS.replen]
  1467.         shl     ax,9
  1468.         out     dx,ax
  1469.         dec     dx              ; 103h
  1470.         mov     al,0
  1471.         out     dx,al
  1472.         add     dx,2
  1473.         mov     al,[Byte cs:si+MS.sc_Mode]
  1474.         out     dx,al
  1475. mt_SetGeneral:
  1476.         call    mt_PerNop
  1477.         mov     dx,[cs:u_Command]
  1478.         mov     al,0ch
  1479.         out     dx,al
  1480.         add     dx,2
  1481.         mov     al,[cs:si+MS.sc_PanPosition]
  1482.         out     dx,al
  1483.         sub     dx,2
  1484.         jmp     @@Bottom
  1485.  
  1486. ;       Shuts off the voice
  1487. @@NoVoice:
  1488.         mov     al,0
  1489.         call    doramp
  1490.         mov     al,0
  1491.         out     dx,al
  1492.         add     dl,2
  1493.         mov     al,3
  1494.         out     dx,al
  1495. @@Bottom:
  1496. @@Done:
  1497.         mov     ax,[cs:si+MS.period]
  1498. ;     call     SpectrumAnalyzer
  1499. ;        ST      n_trigger(A6)
  1500.         mov     [Byte cs:Trigger],1
  1501.         cmp     [Byte cs:EfxFlag],1
  1502.         jz      @@Skip
  1503.         call    mt_CheckMoreEfx
  1504. @@Skip: ret
  1505. endp    sd_UpdateChannels
  1506.  
  1507. proc    mt_dskip near
  1508.         mov     [Word cs:EditSeg],es
  1509.         mov     ax,[Word cs:mt_PatternPos]
  1510.         mov     [Word cs:EditOfs],ax
  1511.     add    [Word cs:mt_PatternPos],48
  1512.         mov     al,[cs:mt_PattDelayTime]
  1513.         or      al,al
  1514.         jz      mt_dskc
  1515.         mov     [cs:mt_PattDelayTime2],al
  1516.         mov     [Byte cs:mt_PattDelayTime],0
  1517. mt_dskc:
  1518.         cmp     [Byte cs:mt_PattDelayTime2],0
  1519.         jz      mt_dska
  1520.         dec     [Byte cs:mt_PattDelayTime2]
  1521.         jz      mt_dska
  1522.     sub    [Word cs:mt_PatternPos],48
  1523. mt_dska:
  1524.         cmp     [Byte cs:mt_PBreakFlag],0
  1525.         jz      mt_nnpysk
  1526.         mov     [Byte cs:mt_PBreakFlag],0
  1527.         xor     ax,ax
  1528.         mov     al,[cs:mt_PBreakPos]
  1529.         mov     [cs:mt_PBreakPos],ah
  1530.     mov    bx,48
  1531.         mul     bx
  1532.     mov    [cs:mt_PatternPos],ax
  1533. mt_nnpysk:
  1534.     cmp    [Word cs:mt_PatternPos],1024*3
  1535.         jb      mt_NoNewPosYet
  1536.  
  1537. mt_NextPosition:
  1538.         xor     ax,ax
  1539.         mov     al,[cs:mt_PBreakPos]
  1540.     mov    bx,48
  1541.     mul    bx
  1542.         mov     [cs:mt_PatternPos],ax
  1543.         mov     [Byte cs:mt_PBreakPos],0
  1544.         mov     [Byte cs:mt_PosJumpFlag],0
  1545.         inc     [Byte cs:mt_SongPos]
  1546.         and     [Byte cs:mt_SongPos],7Fh
  1547.         mov     al,[cs:mt_SongPos]
  1548.     cmp    al,[cs:SongLen]
  1549.         jnz     mt_NoNewPosYet
  1550.         mov     [Byte cs:mt_SongPos],0
  1551.         cmp     [Byte cs:PlayStatus],1
  1552.         jnz     @@Quit
  1553.         mov     [Byte cs:mt_SongPos],0
  1554.         ret
  1555. ;---------------------------------------------------
  1556. @@Quit: mov     [Byte cs:MStatus],1
  1557.         mov     [Byte cs:mt_SongPos],0
  1558.         ret
  1559.  
  1560. mt_NoNewPosYet:
  1561.         cmp     [Byte cs:mt_PosJumpFlag],0
  1562.         jnz     mt_NextPosition
  1563.         ret
  1564. endp    mt_dskip
  1565.  
  1566. proc    mt_CheckEfx near
  1567.     mov    ax,[Word cs:si+MS.cmd]
  1568.         xchg    al,ah
  1569.         and     ax,0FFFh
  1570.         jz      mt_Return
  1571.         mov     bl,[cs:si+MS.cmd]
  1572.         and     bl,0Fh
  1573.         cmp     bl,0
  1574.         jz      mt_Arpeggio
  1575.         cmp     bl,1
  1576.         jz      mt_PortaUp
  1577.         cmp     bl,2
  1578.         jz      mt_PortaDown
  1579.         cmp     bl,3
  1580.         jz      mt_TonePortamento
  1581.         cmp     bl,4
  1582.         jz      mt_Vibrato
  1583.         cmp     bl,5
  1584.         jz      mt_TonePlusVolSlide
  1585.         cmp     bl,6
  1586.         jz      mt_VibratoPlusVolSlide
  1587.         cmp     bl,0Eh
  1588.         jz      mt_E_Commands
  1589. SetBack:call    mt_PerNop
  1590.         cmp     bl,7
  1591.         jz      mt_Tremolo
  1592.         cmp     bl,0Ah
  1593.         jz      mt_VolumeSlide
  1594. mt_Return:
  1595.         ret
  1596. endp    mt_CheckEfx
  1597.  
  1598. ; Effect 0 -- Arpeggio
  1599. proc    mt_Arpeggio near
  1600.         xor     ax,ax
  1601.         mov     al,[cs:mt_counter]
  1602.         mov     bl,3
  1603.         div     bl
  1604.         xchg    al,ah
  1605.         cmp     al,1
  1606.         jz      mt_Arpeggio1
  1607.         cmp     al,2
  1608.         jz      mt_Arpeggio2
  1609. mt_Arpeggio0:
  1610.         mov     cx,[cs:si+MS.period]
  1611.         jmp     ArpeggioSet
  1612.  
  1613. mt_Arpeggio1:
  1614.         xor     ax,ax
  1615.         mov     al,[Byte cs:si+MS.cmdlo]
  1616.         shr     al,4
  1617.         jmp     ArpeggioFind
  1618.  
  1619. mt_Arpeggio2:
  1620.         xor     ax,ax
  1621.         mov     al,[cs:si+MS.cmdlo]
  1622.         and     al,15
  1623. ArpeggioFind:
  1624.         shl     ax,1
  1625.         mov     bx,ax
  1626.         mov     al,[cs:si+MS.finetune]
  1627.     mov    cl,61*2
  1628.         mul     cl
  1629.         mov     dx,[cs:si+MS.period]
  1630.         push    di
  1631.         mov     di,offset mt_PeriodTable
  1632.         add     di,ax
  1633.     mov    cx,60
  1634. mt_arploop:
  1635.         mov     ax,[cs:bx+di]
  1636.         cmp     dx,[cs:di]
  1637.         jnb     mt_arpafterloop
  1638.         add     di,2
  1639.         loop    mt_arploop
  1640.         pop     di
  1641.         ret
  1642. mt_arpafterloop:
  1643.         pop     di
  1644.         mov     cx,ax
  1645.  
  1646. ArpeggioSet:
  1647.         call    mt_PerNop2
  1648.         ret
  1649. endp    mt_Arpeggio
  1650.  
  1651. ; Effect 1 -- Portamento Up
  1652. proc    mt_PortaUp near
  1653.         xor     ax,ax
  1654.         mov     al,[cs:si+MS.cmdlo]
  1655.         and     al,[cs:mt_LowMask]
  1656.         mov     [Byte cs:mt_LowMask],0FFh
  1657.         sub     [cs:si+MS.period],ax
  1658.         mov     cx,[cs:si+MS.period]
  1659.         and     cx,0FFFh
  1660.         cmp     cx,71h
  1661.         jnb     mt_PortaUSkip
  1662.         and     [cs:si+MS.period],0F000h
  1663.         or      [cs:si+MS.period],71h
  1664. mt_PortaUSkip:
  1665.         mov     cx,[cs:si+MS.period]
  1666.         and     cx,0FFFh
  1667.         call    mt_PerNop
  1668.         ret
  1669. endp    mt_PortaUp
  1670.  
  1671.  
  1672. ; Effect 2 -- Portamento Down
  1673. proc    mt_PortaDown near
  1674.         xor     ax,ax
  1675.         mov     al,[cs:si+MS.cmdlo]
  1676.         and     al,[cs:mt_LowMask]
  1677.         mov     [Byte cs:mt_LowMask],0FFh
  1678.         add     [cs:si+MS.period],ax
  1679.         mov     cx,[cs:si+MS.period]
  1680.         and     cx,0FFFh
  1681.         cmp     cx,358h
  1682.         jb      mt_PortaDSkip
  1683.         and     [cs:si+MS.period],0F000h
  1684.         or      [cs:si+MS.period],856
  1685. mt_PortaDSkip:
  1686.         mov     cx,[cs:si+MS.period]
  1687.         and     cx,0FFFh
  1688.         call    mt_PerNop
  1689.         ret
  1690. endp    mt_PortaDown
  1691.  
  1692. proc    mt_SetTonePorta near
  1693.         push    di
  1694.     mov    di,offset mt_PeriodTable
  1695.         mov     bl,[cs:si+MS.note]
  1696.     and    bx,00111111b
  1697.     dec    bx
  1698.     shl    bx,1
  1699.     mov    dx,[Word cs:bx+di]
  1700.         xor     ax,ax
  1701.         mov     al,[cs:si+MS.finetune]
  1702.     mov    cl,61*2
  1703.         mul     cl
  1704.         add     di,ax
  1705.         mov     bx,0
  1706. mt_StpLoop:
  1707.         cmp     dx,[cs:bx+di]
  1708.         jnb     mt_StpFound
  1709.         add     bx,2
  1710.     cmp    bx,61*2
  1711.         jb      mt_StpLoop
  1712.     mov    bx,59*2
  1713. mt_StpFound:
  1714.         mov     dl,[cs:si+MS.finetune]
  1715.         and     dl,8
  1716.         jz      mt_StpGoss
  1717.         or      bx,bx
  1718.         jz      mt_StpGoss
  1719.         sub     bx,2
  1720. mt_StpGoss:
  1721.         mov     dx,[cs:bx+di]
  1722.         pop     di
  1723.         mov     [cs:si+MS.wantedperiod],dx
  1724.         mov     ax,[cs:si+MS.period]
  1725.         mov     [Byte cs:si+MS.toneportdirec],0
  1726.         cmp     dx,ax
  1727.         jz      mt_ClearTonePorta
  1728.         jnb     mt_Return
  1729.         mov     [Byte cs:si+MS.toneportdirec],1
  1730.         ret
  1731.  
  1732. mt_ClearTonePorta:
  1733.         mov     [Word cs:si+MS.wantedperiod],0
  1734.         ret
  1735. endp    mt_SetTonePorta
  1736.  
  1737.  
  1738. ; Effect 3 -- Tone Portamento
  1739. proc    mt_TonePortamento near
  1740.         mov     al,[cs:si+MS.cmdlo]
  1741.         or      al,al
  1742.         jz      mt_TonePortNoChange
  1743.         mov     [cs:si+MS.toneportspeed],al
  1744.         mov     [Byte cs:si+MS.cmdlo],0
  1745. mt_TonePortNoChange:
  1746.         cmp     [Word cs:si+MS.wantedperiod],0
  1747.         jz      mt_Return
  1748.         xor     ax,ax
  1749.         mov     al,[cs:si+MS.toneportspeed]
  1750.         cmp     [Byte cs:si+MS.toneportdirec],0
  1751.         jnz     mt_TonePortaUp
  1752. mt_TonePortaDown:
  1753.         add     [cs:si+MS.period],ax
  1754.         mov     ax,[cs:si+MS.wantedperiod]
  1755.         cmp     ax,[cs:si+MS.period]
  1756.         jg      mt_TonePortaSetPer
  1757.         mov     [cs:si+MS.period],ax
  1758.         mov     [Word cs:si+MS.wantedperiod],0
  1759.         jmp     mt_TonePortaSetPer
  1760.  
  1761. mt_TonePortaUp:
  1762.         sub     [cs:si+MS.period],ax
  1763.         mov     ax,[cs:si+MS.wantedperiod]
  1764.         cmp     ax,[cs:si+MS.period]
  1765.         jl      mt_TonePortaSetPer
  1766.         mov     [cs:si+MS.period],ax
  1767.         mov     [Word cs:si+MS.wantedperiod],0
  1768.  
  1769. mt_TonePortaSetPer:
  1770.         mov     cx,[cs:si+MS.period]
  1771.         mov     al,[cs:si+MS.glissfunk]
  1772.         and     al,0Fh
  1773.         jz      mt_GlissSkip
  1774.         mov     al,[cs:si+MS.finetune]
  1775.     mov    bl,61*2
  1776.         mul     bl
  1777.         push    di
  1778.     mov    di,offset mt_PeriodTable
  1779.         add     di,ax
  1780.         mov     bx,0
  1781. mt_GlissLoop:
  1782.         cmp     cx,[cs:bx+di]
  1783.         jnb     mt_GlissFound
  1784.         add     bx,2
  1785.     cmp    bx,61*2
  1786.         jb      mt_GlissLoop
  1787.     mov    bx,59*2
  1788. mt_GlissFound:
  1789.         mov     cx,[cs:bx+di]
  1790.         pop     di
  1791. mt_GlissSkip:
  1792.         call    mt_PerNop2
  1793.         ret
  1794. endp    mt_TonePortamento
  1795.  
  1796.  
  1797. ; Effect 4 -- Vibrato
  1798. proc    mt_Vibrato near
  1799.         mov     al,[cs:si+MS.cmdlo]
  1800.         or      al,al
  1801.         jz      mt_Vibrato2
  1802.         mov     cl,[cs:si+MS.vibratocmd]
  1803.         and     al,0fh
  1804.         jz      mt_vibskip
  1805.         and     cl,0F0h
  1806.         or      cl,al
  1807. mt_vibskip:
  1808.         mov     al,[cs:si+MS.cmdlo]
  1809.         and     al,0F0h
  1810.         jz      mt_vibskip2
  1811.         and     cl,0Fh
  1812.         or      cl,al
  1813. mt_vibskip2:
  1814.         mov     [cs:si+MS.vibratocmd],cl
  1815. mt_Vibrato2:
  1816.         mov     al,[cs:si+MS.vibratopos]
  1817.         mov     bx,offset mt_VibratoTable
  1818.         shr     ax,2
  1819.         and     ax,001Fh
  1820.         xor     cx,cx
  1821.         mov     cl,[cs:si+MS.wavecontrol]
  1822.         and     cl,03h
  1823.         jz      mt_vib_sine
  1824.         shl     al,3
  1825.         cmp     cl,1
  1826.         jz      mt_vib_rampdown
  1827.         mov     cl,255
  1828.         jmp     mt_vib_set
  1829. mt_vib_rampdown:
  1830.         cmp     [Byte cs:si+MS.vibratopos],0
  1831.         jnl     mt_vib_rampdown2
  1832.         mov     cl,255
  1833.         sub     cl,al
  1834.         jmp     mt_vib_set
  1835. mt_vib_rampdown2:
  1836.         mov     cl,al
  1837.         jmp     mt_vib_set
  1838. mt_vib_sine:
  1839.         add     bl,al
  1840.         mov     cl,[cs:bx]
  1841. mt_vib_set:
  1842.         mov     al,[cs:si+MS.vibratocmd]
  1843.         and     al,15
  1844.         mul     cl
  1845.         shr     ax,7
  1846.         mov     cx,ax
  1847.         mov     ax,[cs:si+MS.period]
  1848.         cmp     [Byte cs:si+MS.vibratopos],0
  1849.         jl      mt_VibratoNeg           ; BMI
  1850.         add     ax,cx
  1851.         jmp     mt_Vibrato3
  1852. mt_VibratoNeg:
  1853.         sub     ax,cx
  1854. mt_Vibrato3:
  1855.         mov     cx,ax
  1856.         call    mt_PerNop2
  1857.         mov     al,[cs:si+MS.vibratocmd]
  1858.         shr     ax,2
  1859.         and     ax,3Ch
  1860.         add     [cs:si+MS.vibratopos],al
  1861.         ret
  1862. endp    mt_Vibrato
  1863.  
  1864.  
  1865. ; Effect 5 -- Tone and Volume Slide
  1866. proc    mt_TonePlusVolSlide near
  1867.         call    mt_TonePortNoChange
  1868.         jmp     mt_VolumeSlide
  1869. endp    mt_TonePlusVolSlide
  1870.  
  1871. ; Effect 6 -- Vibrato and Volume Slide
  1872. proc    mt_VibratoPlusVolSlide near
  1873.         call    mt_Vibrato2
  1874.         jmp     mt_VolumeSlide
  1875. endp    mt_VibratoPlusVolSlide
  1876.  
  1877.  
  1878. ; Effect 7 -- Tremolo
  1879. proc    mt_Tremolo near
  1880.         mov     al,[Byte cs:si+MS.cmdlo]
  1881.         or      al,al
  1882.         jz      mt_Tremolo2
  1883.         mov     cl,[cs:si+MS.tremolocmd]
  1884.         and     al,0Fh
  1885.         jz      mt_treskip
  1886.         and     cl,0F0h
  1887.         or      cl,al
  1888. mt_treskip:
  1889.         mov     al,[Byte cs:si+MS.cmdlo]
  1890.         and     al,0F0h
  1891.         jz      mt_treskip2
  1892.         and     cl,0Fh
  1893.         or      cl,al
  1894. mt_treskip2:
  1895.         mov     [cs:si+MS.tremolocmd],cl
  1896. mt_Tremolo2:
  1897.         mov     al,[cs:si+MS.tremolopos]
  1898.         shr     al,2
  1899.         and     ax,001Fh
  1900.         xor     cx,cx
  1901.         mov     cl,[cs:si+MS.wavecontrol]
  1902.         shr     cl,4
  1903.         and     cl,03h
  1904.         jz      mt_tre_sine
  1905.         shl     al,3
  1906.         cmp     cl,1
  1907.         jz      mt_tre_rampdown
  1908.         mov     cl,255
  1909.         jmp     mt_tre_set
  1910. mt_tre_rampdown:
  1911.         cmp     [Byte cs:si+MS.vibratopos],0
  1912.         jnb     mt_tre_rampdown2
  1913.         mov     cl,255
  1914.         sub     cl,al
  1915.         jmp     mt_tre_set
  1916. mt_tre_rampdown2:
  1917.         mov     cl,al
  1918.         jmp     mt_tre_set
  1919. mt_tre_sine:
  1920.         xor     bx,bx
  1921.         mov     bl,al
  1922.         mov     cl,[cs:bx+offset mt_VibratoTable]
  1923. mt_tre_set:
  1924.         mov     al,[cs:si+MS.tremolocmd]
  1925.         and     al,0Fh
  1926.         mul     cl
  1927.         mov     cx,ax
  1928.         shr     cx,6
  1929.         mov     al,[cs:si+MS.volume]
  1930.         cmp     [Byte cs:si+MS.tremolopos],0
  1931.         jb      mt_TremoloNeg           ; BMI  jns
  1932.         add     al,cl
  1933.         jmp     mt_Tremolo3
  1934. mt_TremoloNeg:
  1935.         sub     al,cl
  1936. mt_Tremolo3:
  1937.         jnb     mt_TremoloSkip
  1938.         xor     ax,ax
  1939. mt_TremoloSkip:
  1940.         cmp     al,40h
  1941.         jb      mt_TremoloOK            ; BLS
  1942.         mov     al,40h
  1943. mt_TremoloOK:
  1944.         call    volequ
  1945.         mov     al,[cs:si+MS.tremolocmd]
  1946.         shr     al,2
  1947.         and     al,3Ch
  1948.         add     [cs:si+MS.tremolopos],al
  1949.         ret
  1950. endp    mt_Tremolo
  1951.  
  1952. ; Effect 9 -- Sample Offset
  1953. proc    mt_SampleOffset near
  1954.         mov     al,[Byte cs:si+MS.cmdlo]
  1955.         or      al,al
  1956.         jz      mt_sononew
  1957.         mov     [cs:si+MS.sampleoffset],al
  1958. mt_sononew:
  1959.         mov     al,[cs:si+MS.sampleoffset]         ; Variance in Protracker code.
  1960.         shl     ax,8
  1961. ;        cmp     ax,[cs:si+MS.reallength]
  1962. ;        jge     mt_sofskip
  1963.         mov     cx,ax
  1964.         or      cx,cx
  1965.         jnz     mt_dontset
  1966.         dec     cx
  1967. mt_dontset:
  1968.         mov     ax,[Word cs:si+MS.start]
  1969.         mov     dx,[Word cs:si+(offset (MS).start)+2]
  1970.         add     ax,cx
  1971.         adc     dx,0
  1972.         mov     [Word cs:si+MS.start],ax
  1973.         mov     [Word cs:si+(offset (MS).start)+2],dx
  1974.         ret
  1975. mt_sofskip:
  1976.         ret
  1977. endp    mt_SampleOffset
  1978.  
  1979.  
  1980. ; Effect A -- Volume Slide
  1981. proc    mt_VolumeSlide near
  1982.         mov     al,[cs:si+MS.cmdlo]
  1983.         shr     al,4
  1984.         or      al,al
  1985.         jz      mt_VolSlideDown
  1986. mt_VolSlideUp:
  1987.         add     [Byte cs:si+MS.volume],al
  1988.         cmp     [Byte cs:si+MS.volume],40h
  1989.         jb      mt_vsuskip
  1990.         mov     [Byte cs:si+MS.volume],40h
  1991. mt_vsuskip:
  1992.         mov     al,[Byte cs:si+MS.volume]
  1993.         call    volequ
  1994.         ret
  1995.  
  1996. mt_VolSlideDown:
  1997.         mov     al,[cs:si+MS.cmdlo]
  1998.         and     al,0Fh
  1999. mt_VolSlideDown2:
  2000.         sub     [Byte cs:si+MS.volume],al
  2001.         jnb     mt_vsdskip
  2002.         mov     [Byte cs:si+MS.volume],0
  2003. mt_vsdskip:
  2004.         mov     al,[Byte cs:si+MS.volume]
  2005.         call    volequ
  2006.         ret
  2007. endp    mt_VolumeSlide
  2008.  
  2009.  
  2010. ; Effect B -- Position Jump
  2011. proc    mt_PositionJump near
  2012.         mov     al,[Byte cs:si+MS.cmdlo]         ; Get where to jump
  2013.         dec     al                            ; Update the
  2014.         mov     [cs:mt_SongPos],al               ; information.
  2015. mt_pj2: mov     [Byte cs:mt_PBreakPos],0
  2016.         mov     [Byte cs:mt_PosJumpFlag],1
  2017.         ret
  2018. endp    mt_PositionJump
  2019.  
  2020. ; Effect C -- Volume Change
  2021. proc    mt_VolumeChange near
  2022.         mov     al,[Byte cs:si+MS.cmdlo]   ; Get value for volume
  2023.         cmp     al,40h                  ; Is it greater than 40h?
  2024.         jb      mt_VolumeOK             ; Nope
  2025.         mov     al,40h
  2026. mt_VolumeOK:
  2027.         mov     [cs:si+MS.volume],al       ; Get it again
  2028.         call    volequ
  2029.         ret
  2030. endp    mt_VolumeChange
  2031.  
  2032. ; Effect D -- Pattern Break
  2033. proc    mt_PatternBreak near
  2034.         mov     al,[Byte cs:si+MS.cmdlo]             ; Break to where?
  2035.         mov     cl,al
  2036.         shr     al,4
  2037.         mov     bl,10
  2038.         mul     bl
  2039.         and     cl,0Fh
  2040.         add     al,cl
  2041.         cmp     al,63
  2042.         jg      mt_pj2
  2043.         mov     [cs:mt_PBreakPos],al
  2044.         mov     [Byte cs:mt_PosJumpFlag],1
  2045.         ret
  2046. endp    mt_PatternBreak
  2047.  
  2048.  
  2049. ; Effect F -- Set Speed
  2050. ;   Doesn't handle Protracker extended speeds.
  2051. proc    mt_SetSpeed near
  2052.         mov     al,[Byte cs:si+MS.cmdlo]             ; Get value for speed
  2053.         or      al,al
  2054.         jz      mt_SpeedLeave
  2055.         cmp     al,32
  2056.         jnb     mt_SpeedExt
  2057. mt_SpeedSet:
  2058.         mov     [Byte cs:mt_counter],0
  2059.         mov     [Byte cs:mt_speed],al
  2060. mt_SpeedLeave:
  2061.         ret
  2062. mt_SpeedExt:
  2063.         ret
  2064. endp    mt_SetSpeed
  2065.  
  2066.  
  2067. proc    mt_CheckMoreEfx near
  2068.     mov    bl,[cs:si+MS.cmd]
  2069.         and     bl,0Fh
  2070.     cmp    bl,09h
  2071.     jz    mt_SampleOffset
  2072.     cmp    bl,0Bh
  2073.     jz    mt_PositionJump
  2074.     cmp    bl,0Dh
  2075.     jz    mt_PatternBreak
  2076.     cmp    bl,0Eh
  2077.     jz    mt_E_Commands
  2078.     cmp    bl,0Fh
  2079.     jz    mt_SetSpeed
  2080.     cmp    bl,0Ch
  2081.     jz    mt_VolumeChange
  2082.     jmp    mt_PerNop
  2083. endp    mt_CheckMoreEfx
  2084.  
  2085. proc    mt_E_Commands near
  2086.         mov     bl,[Byte cs:si+MS.cmdlo]
  2087.         and     bl,0F0h
  2088.         shr     bl,4
  2089.     cmp    bl,0
  2090.     jz    mt_FilterOnOff
  2091.     cmp    bl,1
  2092.     jz    mt_FinePortaUp
  2093.     cmp    bl,2
  2094.     jz    mt_FinePortaDown
  2095.     cmp    bl,3
  2096.     jz    mt_SetGlissControl
  2097.     cmp    bl,4
  2098.     jz    mt_SetVibratoControl
  2099.     cmp    bl,5
  2100.     jz    mt_SetFineTune
  2101.     cmp    bl,6
  2102.     jz    mt_JumpLoop
  2103.     cmp    bl,7
  2104.     jz    mt_SetTremoloControl
  2105.     cmp    bl,0Eh
  2106.     jz    mt_PatternDelay
  2107.     cmp    bl,9
  2108.     jz    mt_RetrigNote
  2109.     cmp    bl,0Ah
  2110.     jz    mt_VolumeFineUp
  2111.     cmp    bl,0Bh
  2112.     jz    mt_VolumeFineDown
  2113.     cmp    bl,0Ch
  2114.     jz    mt_NoteCut
  2115.     cmp    bl,0Dh
  2116.     jz    mt_NoteDelay
  2117.         ret
  2118. endp    mt_E_Commands
  2119.  
  2120. ;──────────────────────────────────────────────────────────────────────────
  2121. ; Effect E
  2122. ;──────────────────────────────────────────────────────────────────────────
  2123. ; Effect 0 -- FilterOnOff
  2124. proc    mt_FilterOnOff near
  2125.         mov     al,[Byte cs:si+MS.cmdlo]
  2126.         and     al,1
  2127.         sal     al,1
  2128.         ; Amiga
  2129.         ; Stuff
  2130.         ret
  2131. endp    mt_FilterOnOff
  2132.  
  2133. ; Effect 1 -- Fine Porta Up
  2134. proc    mt_FinePortaUp near
  2135.         cmp     [Byte cs:mt_counter],0
  2136.         jnz     mt_Return
  2137.         mov     [Byte cs:mt_LowMask],0Fh
  2138.         jmp     mt_PortaUp
  2139. endp    mt_FinePortaUp
  2140.  
  2141. ; Effect 2 -- Fine Porta Down
  2142. proc    mt_FinePortaDown near
  2143.         cmp     [Byte cs:mt_counter],0
  2144.         jnz     mt_Return
  2145.         mov     [Byte cs:mt_LowMask],0Fh
  2146.         jmp     mt_PortaDown
  2147. endp    mt_FinePortaDown
  2148.  
  2149. ; Effect 3 -- Set Gliss Control
  2150. proc    mt_SetGlissControl near
  2151.         mov     al,[Byte cs:si+MS.cmdlo]
  2152.         and     al,0Fh
  2153.         and     [Byte cs:si+MS.glissfunk],0F0h
  2154.         or      [cs:si+MS.glissfunk],al
  2155.         ret
  2156. endp    mt_SetGlissControl
  2157.  
  2158. ; Effect 4 -- Set Vibrato Control
  2159. proc    mt_SetVibratoControl near
  2160.         mov     al,[cs:si+MS.cmdlo]
  2161.         and     al,0Fh
  2162.         and     [Byte cs:si+MS.wavecontrol],0F0h
  2163.         or      [cs:si+MS.wavecontrol],al
  2164.         ret
  2165. endp    mt_SetVibratoControl
  2166.  
  2167. ; Effect 5 -- Set Fine Tune
  2168. proc    mt_SetFineTune near
  2169.         mov     al,[cs:si+MS.cmdlo]
  2170.         and     al,0Fh
  2171.         mov     [cs:si+MS.finetune],al
  2172.         ret
  2173. endp    mt_SetFineTune
  2174.  
  2175. ; Effect 6 -- Jump Loop
  2176. proc    mt_JumpLoop near
  2177.         cmp     [Byte cs:mt_counter],0
  2178.         jnz     mt_Return
  2179.         mov     al,[cs:si+MS.cmdlo]
  2180.         and     al,0Fh
  2181.         jz      mt_SetLoop
  2182.         cmp     [Byte cs:si+MS.loopcount],0
  2183.         jz      mt_jumpcnt
  2184.         dec     [Byte cs:si+MS.loopcount]
  2185.         jz      mt_Return
  2186. mt_jmploop:
  2187.         mov     al,[cs:si+MS.pattpos]
  2188.         mov     [cs:mt_PBreakPos],al
  2189.         mov     [Byte cs:mt_PBreakFlag],1
  2190.         ret
  2191.  
  2192. mt_jumpcnt:
  2193.         mov     [cs:si+MS.loopcount],al
  2194.         jmp     mt_jmploop
  2195.  
  2196. mt_SetLoop:
  2197. ;     xor     dx,dx
  2198.     mov    ax,[cs:mt_PatternPos]
  2199.     mov    bx,48
  2200. ;     call     DivIt
  2201.     div    bl
  2202.     and    ax,63
  2203.         mov     [cs:si+MS.pattpos],al
  2204.         ret
  2205. endp    mt_JumpLoop
  2206.  
  2207. ; Effect 7 -- Set Tremolo Control
  2208. proc    mt_SetTremoloControl near
  2209.         mov     al,[Byte cs:si+MS.cmdlo]
  2210.         and     al,0Fh
  2211.         shl     al,4
  2212.         and     [Byte cs:si+MS.wavecontrol],0Fh
  2213.         or      [cs:si+MS.wavecontrol],al
  2214.         ret
  2215. endp    mt_SetTremoloControl
  2216.  
  2217. ; Effect 9 -- Retrig Note
  2218. proc    mt_RetrigNote near
  2219.         mov     bl,[Byte cs:si+MS.cmdlo]
  2220.         and     bl,0Fh
  2221.         jz      mt_rtnend
  2222.         xor     ax,ax
  2223.         mov     al,[cs:mt_counter]
  2224.         or      al,al
  2225.         jnz     mt_rtnskp
  2226.     mov    al,[cs:si+MS.note]
  2227.     or    al,al
  2228.     jnz    mt_rtnend
  2229. ;        mov     [Byte cs:mt_counter],0
  2230.         xor     ax,ax
  2231.         mov     al,[cs:mt_counter]
  2232. mt_rtnskp:
  2233.         div     bl
  2234.         xchg    ah,al
  2235.         or      al,al
  2236.         jnz     mt_rtnend
  2237. mt_DoRetrig:
  2238.         mov     [Byte cs:EfxFlag],1
  2239.         call    mt_DoIns
  2240.         mov     [Byte cs:EfxFlag],0
  2241. mt_rtnend:
  2242.         ret
  2243. endp    mt_RetrigNote
  2244.  
  2245. ; Effect A -- Volume Fine Up
  2246. proc    mt_VolumeFineUp near
  2247.         cmp     [Byte cs:mt_counter],0
  2248.         jnz     mt_Return
  2249.         mov     al,[cs:si+MS.cmdlo]
  2250.         and     al,0Fh
  2251.         jmp     mt_VolSlideUp
  2252. endp    mt_VolumeFineUp
  2253.  
  2254. ; Effect B -- Volume Fine Down
  2255. proc    mt_VolumeFineDown near
  2256.         cmp     [Byte cs:mt_counter],0
  2257.         jnz     mt_Return
  2258.         mov     al,[cs:si+MS.cmdlo]
  2259.         and     al,0Fh
  2260.         jmp     mt_VolSlideDown2
  2261. endp    mt_VolumeFineDown
  2262.  
  2263. ; Effect C -- Note Cut
  2264. proc    mt_NoteCut near
  2265.         mov     al,[Byte cs:si+MS.cmdlo]
  2266.         and     al,0Fh
  2267.         cmp     al,[cs:mt_counter]
  2268.         jnz     mt_Return
  2269.         mov     [Byte cs:si+MS.volume],0
  2270.         mov     al,[Byte cs:si+MS.volume]
  2271.         call    volequ
  2272.         ret
  2273. endp    mt_NoteCut
  2274.  
  2275. ; Effect D -- Note Delay
  2276. proc    mt_NoteDelay near
  2277.         mov     al,[Byte cs:si+MS.cmdlo]
  2278.         and     al,0Fh
  2279.         cmp     al,[cs:mt_counter]
  2280.         jnz     mt_Return
  2281.     mov    al,[cs:si]
  2282.     and    al,00111111b
  2283.         jz      mt_Return
  2284.         jmp     mt_DoRetrig
  2285. endp    mt_NoteDelay
  2286.  
  2287. ; Effect E -- Pattern Delay
  2288. proc    mt_PatternDelay near
  2289.         cmp     [Byte cs:mt_counter],0
  2290.         jnz     mt_Return
  2291.         mov     al,[Byte cs:si+MS.cmdlo]
  2292.         and     al,0Fh
  2293.         cmp     [Byte cs:mt_PattDelayTime2],0
  2294.         jnz     mt_Return
  2295.         inc     al
  2296.         mov     [cs:mt_PattDelayTime],al
  2297.         ret
  2298. endp    mt_PatternDelay
  2299.  
  2300. proc    doramp near
  2301.         push    bx si
  2302.     mov    ah,0
  2303.     cmp    [Byte cs:si+MS.MasterVolume],0
  2304.         jz      @@ZeroVol
  2305.     mul    [Byte cs:si+MS.MasterVolume]
  2306.     inc    ah
  2307. @@ZeroVol:
  2308.         mov     bl,ah
  2309.     xor    bh,bh
  2310.         shl     bx,1
  2311.         mov     ax,[cs:bx+mt_VolTable]
  2312.         jmp     slideramp2
  2313. slideramp:
  2314.         push    bx si
  2315. slideramp2:
  2316.         mov     si,ax
  2317.         mov     dx,[cs:u_Command]
  2318.         mov     al,0Dh
  2319.         out     dx,al
  2320.         add     dl,2
  2321.         mov     al,3
  2322.         out     dx,al
  2323.         sub     dl,2
  2324.         mov     al,89h
  2325.         out     dx,al
  2326.         inc     dx
  2327.         in      ax,dx
  2328.         push    si
  2329.         push    ax
  2330.         shr     ax,8
  2331.         shr     si,8
  2332.         cmp     ax,si
  2333.         jz      @@Done2
  2334.         jb      @@OK
  2335.         xchg    si,ax
  2336. @@OK:
  2337.         push    ax
  2338.         mov     dx,[cs:u_Command]
  2339.         mov     al,7
  2340.         out     dx,al
  2341.         add     dx,2
  2342.         pop     ax
  2343.         out     dx,al
  2344.         mov     dx,[cs:u_Command]
  2345.         mov     al,8
  2346.         out     dx,al
  2347.         add     dx,2
  2348.         mov     ax,si
  2349.         out     dx,al
  2350.         mov     dx,[cs:u_Command]
  2351.         mov     al,6
  2352.         out     dx,al
  2353.         add     dx,2
  2354.         mov     al,00111111b
  2355.         out     dx,al
  2356.         mov     bl,00000000b
  2357.         pop     ax
  2358.         pop     si
  2359.         cmp     ax,si
  2360.         jb      @@OK2
  2361.         or      bl,01000000b
  2362. @@OK2:
  2363.         mov     dx,[cs:u_Command]
  2364.         mov     al,0Dh
  2365.         out     dx,al
  2366.         add     dx,2
  2367.         mov     al,bl
  2368.         out     dx,al
  2369.         jmp     @@Done
  2370.  
  2371. @@Done2:
  2372.         pop     ax ax
  2373. @@Done:
  2374.         pop     si bx
  2375.         ret
  2376. endp    doramp
  2377.  
  2378. proc    volequ near
  2379.         push    bx si
  2380.     mov    [cs:si+MS.DecVolume],al
  2381.     mov    ah,0
  2382.     cmp    [Byte cs:si+MS.MasterVolume],0
  2383.     jz    @@ZeroVol
  2384.     mul    [Byte cs:si+MS.MasterVolume]
  2385.     inc    ah
  2386. @@ZeroVol:
  2387.     mov    bl,ah
  2388.     xor    bh,bh
  2389.         shl     bx,1
  2390.         mov     ax,[cs:bx+mt_VolTable]
  2391. @@Skip: mov     [cs:si+MS.sc_Vol],ax
  2392.         pop     si bx
  2393.         ret
  2394. endp    volequ
  2395.  
  2396. proc        DivIt    near
  2397.                 or      bx,bx
  2398.                 stc
  2399.                 jz      Div1
  2400.                 mov     cx,ax
  2401.                 mov     ax,dx
  2402.                 xor     dx,dx
  2403.                 div     bx
  2404.                 xchg    cx,ax
  2405.                 div     bx
  2406.                 xchg    dx,cx
  2407.                 clc
  2408. Div1:           ret
  2409. endp            DivIt
  2410.  
  2411. proc            mt_PerNop near
  2412.                 mov     cx,[cs:si+MS.period]    ; get period Value
  2413. proc            mt_PerNop2 near
  2414.                 mov     ax,cx
  2415.                 and     ax,0FFFh
  2416.                 or      ax,ax
  2417.                 jz      @@OutIt
  2418.                 push    dx bx ax
  2419.                 mov     bx,19
  2420.                 mov     dx,36h
  2421.                 mov     ax,9E9Ah
  2422.         call    DivIt
  2423.                 pop     bx
  2424.         call    DivIt
  2425.                 pop     bx dx
  2426. @@OutIt:        mov     [cs:si+MS.sc_Note],ax
  2427.                 ret
  2428. endp            mt_PerNop2
  2429. endp            mt_PerNop
  2430.  
  2431. SizeSoundSeg    =       $-StartSoundSeg
  2432.  
  2433. ends    GUSSound
  2434.  
  2435.